package com.lzy.mall.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import com.alibaba.fastjson.JSON;
import com.lzy.mall.common.to.SkuReductionTo;
import com.lzy.mall.common.to.SpuBoundTo;
import com.lzy.mall.common.to.es.SkuEsModel;
import com.lzy.mall.common.constant.Constant;
import com.lzy.mall.common.utils.PageParaUtils;
import com.lzy.mall.common.utils.PageUtils;
import com.lzy.mall.common.utils.ResultUtils;
import com.lzy.mall.common.vo.SkuStockVO;
import com.lzy.mall.product.entity.*;
import com.lzy.mall.product.dao.PmsSpuInfoDao;
import com.lzy.mall.product.feign.CouponFeignService;
import com.lzy.mall.product.feign.SearchFeignService;
import com.lzy.mall.product.feign.WareFeignService;
import com.lzy.mall.product.service.*;
import com.lzy.mall.product.domain.PmsEnum;
import com.lzy.mall.product.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.beetl.sql.core.engine.PageQuery;
import org.beetl.sql.core.query.LambdaQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * spu信息(PmsSpuInfo)表服务实现类
 *
 * @author lzy
 * @since 2021-08-25 11:41:25
 */
@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class PmsSpuInfoServiceImpl implements PmsSpuInfoService {
    private final PmsSpuInfoDao spuInfoDao;

    private final PmsSpuInfoDescService infoDescService;

    private final PmsSpuImagesService spuImagesService;

    private final PmsProductAttrValueService attrValueService;

    private final PmsAttrService attrService;

    private final PmsSkuInfoService skuInfoService;

    private final PmsSkuImagesService skuImagesService;

    private final PmsSkuSaleAttrValueService skuSaleAttrValueService;

    private final CouponFeignService couponFeignService;

    private final PmsBrandService brandService;

    private final PmsCategoryService categoryService;

    private final WareFeignService wareFeignService;

    private final SearchFeignService searchFeignService;

    @Override
    @Transactional
    public void saveSpuInfo(SpuSaveVo vo) {

        Date now = DateUtil.date();

        //1.保存spu基本信息 pms_spu_info
        PmsSpuInfo info = new PmsSpuInfo();
        BeanUtil.copyProperties(vo,info);
        info.setCreateTime(now);
        info.setUpdateTime(now);
        spuInfoDao.insertTemplate(info,true);
        //2.保存spu的描述图片 pms_spu_info_desc
        List<String> decript = vo.getDecript();
        PmsSpuInfoDesc spuInfoDesc = PmsSpuInfoDesc.builder()
                .spuId(info.getId())
                .decript(StrUtil.join(",", decript))
                .build();
        infoDescService.save(spuInfoDesc);

        //3.保存spu的图片集 pms_spu_images
        List<String> images = vo.getImages();
        spuImagesService.saveImages(info.getId(),images);

        //4.保存spu的规格参数 pms_product_attr_value
        List<BaseAttrsVo> baseAttrs = vo.getBaseAttrs();
        List<PmsProductAttrValue> attrValues = baseAttrs.stream().map(attrsVo -> {
            PmsAttr attr = attrService.getById(attrsVo.getAttrId());
            return PmsProductAttrValue.builder()
                    .attrId(attrsVo.getAttrId())
                    .attrName(attr.getAttrName())
                    .spuId(info.getId())
                    .attrValue(attrsVo.getAttrValues())
                    .quickShow(attrsVo.getShowDesc())
                    .build();
        }).collect(Collectors.toList());
        attrValueService.saveBatch(attrValues);

        //5.保存spu的积分信息 mall_sms -> sms_spu_bounds
        BoundVo bounds = vo.getBounds();
        SpuBoundTo spuBoundTo = new SpuBoundTo();
        BeanUtil.copyProperties(bounds,spuBoundTo);
        spuBoundTo.setSpuId(info.getId());
        couponFeignService.saveSpuBounds(spuBoundTo);

        //6.保存当前spu对应的所有sku信息
        List<SkusVo> skus = vo.getSkus();
        if (CollUtil.isNotEmpty(skus)){
            skus.forEach(item -> {
                String defaultImg = "";
                for (Images image : item.getImages()) {
                    if(image.getDefaultImg() == 1){
                        defaultImg = image.getImgUrl();
                    }
                }
                //6.1、sku的基本信息 pms_sku_info
                PmsSkuInfo skuInfo = new PmsSkuInfo();
                BeanUtils.copyProperties(item,skuInfo);
                skuInfo.setBrandId(info.getBrandId());
                skuInfo.setCatalogId(info.getCatalogId());
                skuInfo.setSaleCount(0L);
                skuInfo.setSpuId(info.getId());
                skuInfo.setSkuDefaultImg(defaultImg);
                Long skuId = skuInfoService.save(skuInfo);

                //6.2、sku的图片信息 pms_sku_images
                List<Images> imagesList = item.getImages();
                List<PmsSkuImages> skuImages = imagesList.stream().map(img -> {
                    return PmsSkuImages.builder()
                            .imgUrl(img.getImgUrl())
                            .defaultImg(img.getDefaultImg())
                            .skuId(skuId)
                            .build();
                }).filter(a -> StrUtil.isNotEmpty(a.getImgUrl()))
                        .collect(Collectors.toList());
                skuImagesService.saveBatch(skuImages);

                //6.3、sku的销售属性信息 pms_sku_sale_attr_value
                List<Attr> attrs = item.getAttr();
                List<PmsSkuSaleAttrValue> attrValueList = attrs.stream().map(attr -> {
                    PmsSkuSaleAttrValue attrValue = new PmsSkuSaleAttrValue();
                    BeanUtil.copyProperties(attr, attrValue);
                    attrValue.setSkuId(skuId);
                    return attrValue;
                }).collect(Collectors.toList());
                skuSaleAttrValueService.saveBatch(attrValueList);

                //6.4、sku的优惠、满减等信息  mall_sms -> sms_sku_ladder  sms_coupon  sms_sku_full_reduction
                SkuReductionTo skuReductionTo = new SkuReductionTo();
                BeanUtil.copyProperties(item,skuReductionTo);
                skuReductionTo.setSkuId(skuId);
                if(skuReductionTo.getFullCount() >0 || skuReductionTo.getFullPrice().compareTo(BigDecimal.ZERO) == 1){
                    ResultUtils r1 = couponFeignService.saveSkuReduction(skuReductionTo);
                }
            });
        }

    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {

        LambdaQuery<PmsSpuInfo> lambdaQuery = spuInfoDao.createLambdaQuery();

        String key = (String) params.get("key");
        //where  (id=1 or spu_name like xxx)
        if(StrUtil.isNotEmpty(key)){
            lambdaQuery.and(
                    lambdaQuery.condition()
                            .andEq(PmsSpuInfo::getId,key)
                            .orLike(PmsSpuInfo::getSpuName,"%" + key + "%"));
        }
        // status=1 and (id=1 or spu_name like xxx)
        String status = (String) params.get("status");
        if(StrUtil.isNotEmpty(status)){
            lambdaQuery.andEq(PmsSpuInfo::getPublishStatus,status);
        }

        String brandId = (String) params.get("brandId");
        if(StrUtil.isNotEmpty(brandId) && !Constant.ALL_LIST_ID.equalsIgnoreCase(brandId)){
            lambdaQuery.andEq(PmsSpuInfo::getBrandId,brandId);
        }

        String catelogId = (String) params.get("catelogId");
        if(StrUtil.isNotEmpty(catelogId) && !Constant.ALL_LIST_ID.equalsIgnoreCase(catelogId)){
            lambdaQuery.andEq(PmsSpuInfo::getCatalogId,catelogId);
        }
        PageQuery pageQuery = PageParaUtils.pagePara(params);
        PageQuery<PmsSpuInfo> page = lambdaQuery.page(pageQuery.getPageNumber(), pageQuery.getPageSize());

        return new PageUtils(page);
    }

    @Override
    @Transactional
    public void spuUp(Long spuId) {

        List<PmsSkuInfo> skuInfos = skuInfoService.getSkuBySpuId(spuId);
        log.info("skuInfos:{}",skuInfos);
        List<Long> skuIds = skuInfos.stream()
                .map(PmsSkuInfo::getSkuId)
                .collect(Collectors.toList());

        //TODO 公共的在循环外查询一次即可 4.查询当前sku的所有可以被用来检索的规格属性
        List<PmsProductAttrValue> attrValues = attrValueService.baseAttrlistforspu(spuId);
        List<Long> attrIds = attrValues.stream()
                .map(PmsProductAttrValue::getAttrId)
                .collect(Collectors.toList());
        // 收取出 attrIds 中可以被检索的id
        List<Long> searchAttrIds =  attrService.searchAttrIds(attrIds);

        List<SkuEsModel.Attr> attrs = attrValues.stream()
                .filter(item -> searchAttrIds.contains(item.getAttrId()))
                .map(productAttrValue -> {
                    SkuEsModel.Attr attr = new SkuEsModel.Attr();
                    BeanUtil.copyProperties(productAttrValue, attr);
                    return attr;
                }).collect(Collectors.toList());

        //TODO 1.发送远程调用，库存系统查询是否有库存
        List<SkuStockVO> skuStock = null;
        Map<Long,Boolean> stockMap = null;
        try {
            //TODO 返回值为List<SkuStockVO>,改为ResultUtils<List<SkuStockVO>>
            skuStock = wareFeignService.getSkuStock(skuIds);
            log.info("库存系统查询结果：{}" , skuStock);

            stockMap = skuStock.stream().collect(Collectors.toMap(SkuStockVO::getSkuId, item -> item.getStock() > 0));
//            JSONObject jsonObject = new JSONObject();
//            skuStock.forEach(skuStockVO -> {
//                jsonObject.putOpt(skuStockVO.getSkuId().toString(),skuStockVO.getStock()>0?true:false);
//            });
//            stockMap = JSON.parseObject(jsonObject.toString(), Map.class);
        } catch (Exception e) {
            log.info("远程调用库存系统异常，以原因：{}",e);
        }
        log.info("-----map{}",stockMap);
        Map<Long,Boolean> finalStockMap = stockMap;
        log.info("----finalStockMap:{}",finalStockMap);
        List<SkuEsModel> esModels = skuInfos.stream().map(sku -> {
            //组装需要的数据
            SkuEsModel esModel = new SkuEsModel();
            BeanUtil.copyProperties(sku,esModel);

            esModel.setSkuPrice(sku.getPrice());
            esModel.setSkuImg(sku.getSkuDefaultImg());

            if (ObjectUtil.isNotNull(finalStockMap)) {
                esModel.setHasStock(true);
            } else {
                //设置库存信息
                Boolean hasStock = finalStockMap.get(sku.getSkuId());
                log.info("skuId:{},hasStock:{}", sku.getSkuId(),hasStock);
                esModel.setHasStock(hasStock);
            }


            //TODO 2.热度评分，暂时默认为0
            esModel.setHotScore(0L);

            //TODO 3.查询品牌和分类的名字信息
            PmsBrand brand = brandService.getById(sku.getBrandId());
            esModel.setBrandName(brand.getName());
            esModel.setBrandImg(brand.getLogo());

            PmsCategory category = categoryService.getById(sku.getCatalogId());
            esModel.setCatalogName(category.getName());

            esModel.setAttrs(attrs);

            return esModel;
        }).collect(Collectors.toList());

        //TODO 5.将数据发送给es进行保存：mall-search
        try {
            searchFeignService.productStatusUp(esModels);

            //TODO 6.修改当前spu状态
            PmsSpuInfo single = spuInfoDao.single(spuId);
            single.setPublishStatus(PmsEnum.SPU_UP.getCode());
            single.setUpdateTime(DateUtil.date());
            spuInfoDao.updateTemplateById(single);
        } catch (Exception e) {
            //TODO 7.远程调用失败，重复调用？接口幂等性：重复机制？
            log.info("远程调用失败,原因:{}" + e);
        }
    }

    @Override
    public PmsSpuInfo getSkuInfoBySkuId(Long skuId) {
        PmsSkuInfo skuInfo = skuInfoService.getById(skuId);
        PmsSpuInfo single = spuInfoDao.single(skuInfo.getSpuId());
        return single;
    }
}
